﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using WoogiUI;
using System.Linq;
using Demo;

public enum ParentType
{
    canvas,
    plane,
}
public enum Method
{
    setButton,
    setButtonInteractable,
    setText,
    setImg,
    setScrollBarEvent,
    setToggleEvent,
    setSliderEvent,
}
public sealed class UIManager
{
    private static UIManager instance;
    public static UIManager Instance
    {
        get
        {
            if (instance == null)
                instance = new UIManager();
            return instance;
        }
    }

    private Dictionary<string, WoogiPlane> planeDictionary = new Dictionary<string, WoogiPlane>();
    private Dictionary<string, WoogiCanvas> canvasDictionary = new Dictionary<string, WoogiCanvas>();
    #region region and destory
    public void DestroyPlane(PanelEnum planeName, bool isAuto = false)
    {
        DestroyPlane(planeName.ToString(), isAuto);
    }

    public void DestroyPlane(string planeName, bool isAuto = false)
    {
        if (OpenPanle.ContainsKey(planeName))
        {
            OpenPanle[planeName] = null;
            OpenPanle.Remove(planeName);
        }
        if (Destory<WoogiPlane>(ref planeDictionary, planeName, isAuto))
        {
            //TODO 每次关闭 面板的时候 需要 对内存做一次清理工作
#if UNITY_IPHONE//UNITY_ANDROID || UNITY_IPHONE
    
#endif
            ResourceManager.FressAssetsNow();
        }
    }

    public void DestroyCanvas(string cavasName, bool isAuto = false)
    {
        if (Destory<WoogiCanvas>(ref canvasDictionary, cavasName, isAuto)) { }
        //    Debug.Log("destory canvas:" + cavasName + " succeed!");
        //else
        //    Debug.Log("destory canvas:" + cavasName + " failure!");
    }

    internal void RegisterPlane(string name, WoogiPlane plane)
    {
        Register<WoogiPlane>(ref planeDictionary, name, plane);
    }

    internal void RegisterCanvas(string name, WoogiCanvas canvas)
    {
        Register<WoogiCanvas>(ref canvasDictionary, name, canvas);
    }

    private void Register<T>(ref Dictionary<string, T> dictionary, string name, T t) where T : MonoBehaviour
    {
        if (dictionary == null) dictionary = new Dictionary<string, T>();
        if (dictionary.ContainsKey(name))
        {
            dictionary[name] = t;
        }
        else
        {
            dictionary.Add(name, t);
        }
    }

    private bool Destory<T>(ref Dictionary<string, T> dictionary, string name, bool isAuto) where T : MonoBehaviour
    {
        if (dictionary == null) return false;
        if (dictionary.ContainsKey(name))
        {
            T t = default(T);
            if (dictionary[name] == null)
            {
                dictionary.Remove(name);
                return false;
            }
            if (!isAuto)
            {
                t = dictionary[name];
                GameObject.Destroy(t.gameObject);
            }
            dictionary[name] = null;
            dictionary.Remove(name);
        }
        return true;
    }
    #endregion

    #region get canvas and plane
    public WoogiPlane GetPlane(string planeName, bool b = false)
    {
        if (CheckPanel(planeName))
        {
            return planeDictionary[planeName];
        }
        return null;
    }

    public GameObject GetPlaneGameObject(string planeName)
    {
        WoogiPlane plane = GetPlane(planeName);
        if (plane != null)
            return plane.gameObject;
        return null;
    }

    public Transform GetPlaneTransform(string planeName)
    {
        WoogiPlane plane = GetPlane(planeName);
        if (plane != null)
            return plane.transform;
        return null;
    }

    public RectTransform GetPlaneRectTransform(string planeName)
    {
        WoogiPlane plane = GetPlane(planeName);
        if (plane != null)
            return plane.GetComponent<RectTransform>();
        return null;
    }

    /// <summary>
    /// genericity only both class type : Transfrom and GameObject
    /// </summary>
    /// <typeparam name="T">Transfrom or GameObject</typeparam>
    /// <param name="name">object name</param>
    /// <returns>T</returns>
    public T GetPlane<T>(string name) where T : Component
    {
        return GetObject<T>(GetObject<WoogiPlane>(planeDictionary, name), name);
    }

    /// <summary>
    /// genericity only both class type : Transfrom and GameObject
    /// </summary>
    /// <typeparam name="T">Transfrom or GameObject</typeparam>
    /// <param name="name">object name</param>
    /// <returns>T</returns>
    public T GetCanvas<T>(string name) where T : Component
    {
        return GetObject<T>(GetObject<WoogiCanvas>(canvasDictionary, name), name);
    }

    private T GetObject<T>(GameObject go, string name) where T : Component
    {
        if (go != null)
        {
            return go.GetComponent<T>();
        }
        return default(T);
    }

    private GameObject GetObject<T>(Dictionary<string, T> dictionary, string name) where T : Component
    {
        GameObject t = default(GameObject);
        if (dictionary == null) return t;
        if (dictionary.ContainsKey(name))
        {
            if (dictionary[name] != null)
                return dictionary[name].gameObject;
            else
                dictionary.Remove(name);
        }
        return t;
    }
    #endregion

    #region load 
    public bool LoadCanvas(string path, Transform parentTransfrom)
    {
        UnityEngine.Object obj = GetPrefab(path);
        if (obj != null)
        {
            GameObject go = GameObject.Instantiate(obj) as GameObject;
            go.name = go.name.Replace("(Clone)", "");
            if (parentTransfrom != null)
            {
                go.transform.SetParent(parentTransfrom);
                if (!go.activeSelf)
                    go.GetComponent<WoogiCanvas>().Regist();
                return true;
            }
        }
        return false;
    }


    Dictionary<string, GameObject> OpenPanle = new Dictionary<string, GameObject>();
    public GameObject LoadPlane(string path, string parentCanvasName)
    {
        string panelName = path.Substring(path.LastIndexOf("/")).Replace("/", "");
        if (OpenPanle.ContainsKey(panelName))
        {
            if (OpenPanle[panelName] != null)
            {
                OpenPanle[panelName].transform.SetAsLastSibling();
                return OpenPanle[panelName];
            }
            else
            {
                OpenPanle.Remove(panelName);
            }
        }

        Transform parent = null;
        try
        {
            parent = GetCanvas<Transform>(parentCanvasName);
        }
        catch (Exception e)
        {
            Debug.LogError(e.Message + " " + Application.loadedLevelName);
        }
        if (parent != null)
        {
            UnityEngine.Object obj = ResourceManager.Load<UnityEngine.Object>(path);
            if (obj != null)
            {
                GameObject go = GameObject.Instantiate(obj) as GameObject;
                go.name = go.name.Replace("(Clone)", "");
                RectTransform rectTrans = go.transform.GetComponent<RectTransform>();
                Vector3 oldPos = rectTrans.anchoredPosition3D;
                Vector2 oldSize = rectTrans.sizeDelta;
                go.transform.SetParent(parent);
                rectTrans.sizeDelta = oldSize;
                rectTrans.anchoredPosition3D = oldPos;
                go.transform.localScale = Vector3.one;
                if (!go.activeSelf)
                    go.GetComponent<WoogiPlane>().Regist();
                OpenPanle[panelName] = go;
                go.transform.SetAsLastSibling();
                return go;
            }
        }
        return null;
    }

    public GameObject LoadPlane(PanelEnum pe, string parentCanvasName = "CentreLayer")
    {
        return LoadPlane("Panel/" + pe.ToString(), parentCanvasName);
    }

    public void RemoveAllPanel()
    {
        // instance = null;
        //List<string> allPanleKey = new List<string>();
        //foreach( string key in OpenPanle.Keys )
        //{
        //    allPanleKey.Add(key);
        //}
        //foreach(string key in  allPanleKey)
        //{
        //    DestroyPlane(key);
        //}
    }

    public static void BindButtonEvent(MonoBehaviour recveiObj, WoogiButton btn, ButtonEvent _ButtonEvent)
    {
        if (btn == null)
        {
            Debug.LogError("btn is null");
            return;
        }
        btn.SetEvent(recveiObj, UIEventType.mouseClick, _ButtonEvent);
    }

    public static void BindTransParentButtonEvent(TransparentButton btn, TransparentButton.ButtonEvent _ButtonEvent)
    {
        if (btn == null)
        {
            Debug.LogError("btn is null");
            return;
        }
        btn.btEvent = _ButtonEvent;
    }

    public static void BindToggleEvent(WoogiToggle btn, Action<bool, GameObject> callbackEvent)
    {
        if (btn == null)
        {
            Debug.LogError("btn is null");
            return;
        }
        btn.SetEvent(callbackEvent);
    }

    #region load  Prefab.
    public bool LoadGameObject(string path, string parentPlaneName)
    {
        GameObject go = LoadGameObject(path, GetPlane<Transform>(parentPlaneName));
        if (go != null)
            return true;
        return false;
    }
    public GameObject LoadGameObject(string path, Transform parentTransform)
    {
        UnityEngine.Object obj = GetPrefab(path);
        if (obj != null)
        {
            GameObject go = GameObject.Instantiate(obj) as GameObject;
            go.name = go.name.Replace("(Clone)", "");
            if (parentTransform != null)
            {
                go.transform.SetParent(parentTransform);
                go.transform.localScale = Vector3.one;
                go.transform.localPosition = Vector3.zero;
                return go;
            }
            else
            {
                GameObject.Destroy(go);
            }
        }
        return null;
    }

    public UnityEngine.Object GetPrefab(string path)
    {
        return ResourceManager.Load<UnityEngine.Object>(path);
    }
    #endregion

    #region 获取本地icon
    /// <summary>
    /// The default icon.
    /// </summary>
    public Sprite defaultIcon;
    /// <summary>
    /// Gets the icon.
    /// </summary>
    /// <returns>The icon.</returns>
    /// <param name="icon">Icon.</param>
    public Sprite GetIcon(string icon)
    {
        if (defaultIcon == null)
            defaultIcon = ResourceManager.Load<Sprite>("UI/Icons/Default");
        object obj = ResourceManager.Load<Sprite>("UI/Icons/" + icon);
        if (obj == null)
        {
            Debug.Log("Did not find  file = " + icon);
            return defaultIcon;
        }
        else
            return obj as Sprite;
    }
    #endregion
    #endregion


    private bool CheckPanel(string panelName)
    {
        if (planeDictionary.ContainsKey(panelName))
        {
            if (planeDictionary[panelName] != null)
                return true;
            else
                planeDictionary.Remove(panelName);
        }
        return false;
    }

    #region 设置激活状态
    /// <summary>
    /// set panle active 
    /// </summary>
    /// <param name="planeName">plane name</param>
    /// <param name="value">bool value</param>
    public void SetActivePanel(string planeName, bool value)
    {
        if (CheckPanel(planeName))
        {
            planeDictionary[planeName].gameObject.SetActive(value);
        }
    }

    public bool ActiveSelfPanel(string planeName)
    {
        if (CheckPanel(planeName))
        {
            return planeDictionary[planeName].gameObject.activeSelf;
        }
        return false;
    }
    #endregion

    /// <summary>
    /// get gameobject
    /// </summary>
    /// <param name="objName">object name（plane.image）</param>
    /// <returns>GameObject</returns>
    public GameObject GetGameObject(string objName)
    {
        string[] list = objName.Split('.');
        if (list == null || list.Length != 2)
            return null;
        if (CheckPanel(list[0]))
        {
            return planeDictionary[list[0]].GetGameObject(list[1]);
        }
        return null;
    }

    public RectTransform GetRectTransform(string objName)
    {
        return UGUIEx.GetRectTransform(GetGameObject(objName));
    }

    public T GetObj<T>(string objectname) where T : Component
    {
        GameObject go = GetGameObject(objectname);
        if (go != null)
        {
            return go.GetComponent<T>();
        }
        return default(T);
    }

    public Component GetObj(string objectname, string type)
    {
        GameObject go = GetGameObject(objectname);
        if (go != null)
        {
            return go.GetComponent(type);
        }
        return null;
    }

    public Component[] GetObjsInChildren(GameObject go, string type)
    {
        if (go != null)
        {
            return go.GetComponentsInChildren(Type.GetType(type));
        }
        return null;
    }



    /// <summary>
    /// check current click object whether to be included
    /// </summary>
    /// <param name="obj">arrayList parent object</param>
    /// <param name="go">current click object</param>
    /// <returns></returns>
    public static bool FindGameObject(Transform obj, GameObject go)
    {
        int length = obj.childCount;
        for (int i = 0; i < length; i++)
        {
            Transform childGo = obj.GetChild(i);
            if (go == childGo.gameObject)
            {
                return true;
            }
            else
            {
                if (FindGameObject(childGo, go))
                {
                    return true;
                }
            }
        }
        return false;
    }
    /// <summary>
    /// 抛弃 请使用 SpaceWorldPositionToUIWorldPosition
    /// </summary>
    /// <param name="transf"></param>
    /// <param name="worldGo"></param>
    /// <returns></returns>
    public static Vector3 WorldToUIPoint(Transform transf, Vector3 worldGo)
    {
        if (transf == null)
        {
            Debug.LogError("WorldToUIPoint value is null!");
            return Vector2.zero;
        }
        Canvas canvas = transf.GetComponentInParent<Canvas>();
        CanvasScaler canvasScaler = canvas.GetComponent<CanvasScaler>();
        float offect = (Screen.width / canvasScaler.referenceResolution.x) * (1 - canvasScaler.matchWidthOrHeight) + (Screen.height / canvasScaler.referenceResolution.y) * canvasScaler.matchWidthOrHeight;
        Vector2 a = RectTransformUtility.WorldToScreenPoint(Camera.main, worldGo);
        return new Vector2(a.x / offect, a.y / offect);
    }

    /// <summary>
    /// 3d 空间坐标映射到 屏幕的UI坐标.
    /// </summary>
    /// <param name="transf">show obj</param>
    /// <param name="worldPosition">空间坐标</param>
    /// <returns> UI world Position </returns>
    public static Vector3 SpaceWorldPositionToUIWorldPosition(Transform transf, Vector3 worldPosition)
    {
        if (transf == null)
        {
            Debug.LogError("WorldToUIPoint Transform is null!");
            return Vector2.zero;
        }
        Canvas canvas = transf.GetComponentInParent<Canvas>();
        return SpaceWorldPositionToUIWorldPosition(canvas, worldPosition);
    }

    public static Vector3 SpaceWorldPositionToUIWorldPosition(Canvas canvas, Vector3 worldPosition)
    {
        if (canvas == null || Camera.main == null)
        {
            //Debug.LogError("SpaceWorldToUIWorldPosition canvas is null!");
            return Vector2.zero;
        }
        Vector3 pos = Camera.main.WorldToScreenPoint(worldPosition);
        if (canvas.worldCamera != null)
        {
            pos = canvas.worldCamera.ScreenToWorldPoint(new Vector3(pos.x, pos.y, canvas.planeDistance));
        }
        return pos;
    }


    public static T LoadLocalResource<T>(string path) where T : UnityEngine.Object
    {
        T t = ResourceManager.Load<T>(path);
        return t;
    }

    public void OnDestroy()
    {
        planeDictionary.Clear();
    }
}


